<link rel="import" href="../../../../packages/polymer/polymer.html">
<link rel="import" href="code_ref.html">
<link rel="import" href="function_ref.html">
<link rel="import" href="nav_bar.html">
<link rel="import" href="observatory_element.html">
<link rel="import" href="sliding_checkbox.html">
<link rel="import" href="view_footer.html">

<polymer-element name="cpu-profile-table" extends="observatory-element">
  <template>
    <link rel="stylesheet" href="css/shared.css">
    <nav-bar>
      <top-nav-menu></top-nav-menu>
      <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
      <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
      <nav-menu link="{{ makeLink('/profiler-table', isolate) }}" anchor="cpu profile (table)" last="{{ true }}"></nav-menu>
      <nav-refresh callback="{{ refresh }}"></nav-refresh>
      <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
    </nav-bar>
    <style>
      /* general */
      .well {
        background-color: #ECECEC;
        padding: 0.2em;
      }
      .center {
        align-items: center;
        justify-content: center;
      }

      /* status messages */
      .statusMessage {
        font-size: 150%;
        font-weight: bold;
      }
      .statusBox {
        height: 100%;
        padding: 1em;
      }

      /* tables */
      .table {
        border-collapse: collapse!important;
        table-layout: fixed;
        height: 100%;
      }
      .th, .td {
        padding: 8px;
        vertical-align: top;
      }
      .table thead > tr > th {
        vertical-align: bottom;
        text-align: left;
        border-bottom:2px solid #ddd;
      }
      .spacer {
        width: 16px;
      }
      .left-border-spacer {
        width: 16px;
        border-left: 1px solid;
      }
      .clickable {
        color: #0489c3;
        text-decoration: none;
        cursor: pointer;
        min-width: 8em;
      }
      .clickable:hover {
        text-decoration: underline;
        cursor: pointer;
      }
      tr:hover:not(.focused) > td {
        background-color: #FAFAFA;
      }
      .focused {
        background-color: #F4C7C3;
      }
      .scroll {
        overflow: scroll;
      }
      .outlined {
        -webkit-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
        -moz-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
        box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
        margin: 4px;
      }
      .centered {
        margin-left: auto;
        margin-right: auto;
        justify-content: center;
      }
      .full-height {
        height: 100%;
      }
      .mostly-full-height {
        height: 80%;
      }
      .full-width {
        width: 100%;
      }
      .focused-function-label {
        flex: 0 1 auto;
        margin-left: auto;
        margin-right: auto;
        justify-content: center;
      }
      .call-table {
        flex: 1 1 auto;
      }

      .tree {
        border-spacing: 0px;
        width: 100%;
        margin-bottom: 20px
        vertical-align: middle;
      }

      .tree tbody tr {
        animation: fadeIn 0.5s;
        -moz-animation: fadeIn 0.5s;
        -webkit-animation: fadeIn 0.5s;
      }

      .tree tbody tr:hover {
        background-color: #FAFAFA;
      }

      .tree tr td:first-child,
      .tree tr th:first-child {
        width: 100%;
      }

      .tree thead > tr > th {
        padding: 8px;
        vertical-align: bottom;
        text-align: left;
        border-bottom: 1px solid #ddd;
      }

    </style>
    <div class="content-centered-big">
      <template if="{{ state == 'Requested' }}">
        <div class="statusBox shadow center">
          <div class="statusMessage">Fetching profile from VM...</div>
        </div>
      </template>
      <template if="{{ state == 'Loading' }}">
        <div class="statusBox shadow center">
          <div class="statusMessage">Loading profile...</div>
        </div>
      </template>
      <template if="{{ state == 'Disabled' }}">
        <div class="statusBox shadow center">
          <div>
            <h1>Profiling is disabled</h1>
            <br>
            Perhaps the <b>profile</b> flag has been disabled for this VM.
            <br><br>
            See all
            <a on-click="{{ goto }}" _href="{{ gotoLink('/flags') }}">vm flags</a>
          </div>
        </div>
      </template>
      <template if="{{ state == 'Exception' }}">
        <div class="statusBox shadow center">
          <div class="statusMessage">
            <h1>Profiling is disabled due to unexpected exception:</h1>
            <br>
            <pre>{{ exception.toString() }}</pre>
            <br>
            <h1>Stack trace:</h1>
            <br>
            <pre>{{ stackTrace.toString() }}</pre>
          </div>
        </div>
      </template>
      <template if="{{ state == 'Loaded' }}">
        <div class="memberList">
          <div class="memberItem">
            <div class="memberName">Refreshed at </div>
            <div class="memberValue">{{ refreshTime }} (fetched in {{ fetchTime  }}) (loaded in {{ loadTime }})</div>
          </div>
          <div class="memberItem">
            <div class="memberName">Profile contains</div>
            <div class="memberValue">{{ sampleCount }} samples (spanning {{ timeSpan }})</div>
          </div>
          <div class="memberItem">
            <div class="memberName">Sampling</div>
            <div class="memberValue">{{ stackDepth }} stack frames @ {{ sampleRate }} Hz</div>
          </div>
          <div class="memberItem">
            <div class="memberName">Call Tree Direction</div>
            <div class="memberValue">
              <select value="{{directionSelector}}">
                <option value="Down">Top down</option>
                <option value="Up">Bottom up</option>
              </select>
            </div>
          </div>
        </div>
      </template>
    </div>
    <hr>
    <div id="main" class="flex-row centered">
      <div class="flex-item-45-percent full-height outlined scroll">
        <table id="main-table" class="flex-item-100-percent table">
          <thead>
          <tr>
            <th on-click="{{changeSortProfile}}" class="clickable" title="Executing (%)">{{ profileTable.getColumnLabel(0) }}</th>
            <th on-click="{{changeSortProfile}}" class="clickable" title="In stack (%)">{{ profileTable.getColumnLabel(1) }}</th>
            <th on-click="{{changeSortProfile}}" class="clickable" title="Method">{{ profileTable.getColumnLabel(2) }}</th>
          </tr>
          </thead>
          <tbody id="profile-table">
          </tbody>
        </table>
      </div>
      <div class="flex-item-45-percent full-height outlined">
        <div class="flex-column full-height">
          <div class="focused-function-label">
            <template if="{{ focusedFunction != null }}">
              <span>Focused on: </span>
              <function-ref ref="{{ focusedFunction }}"></function-ref>
            </template>
            <template if="{{ focusedFunction == null }}">
              <span>No focused function</span>
            </template>
          </div>
          <hr>
          <div class="call-table scroll">
            <table class="full-width table">
              <thead>
              <tr>
                <th on-click="{{changeSortCallers}}" class="clickable" title="Callers (%)">{{ profileCallersTable.getColumnLabel(0) }}</th>
                <th on-click="{{changeSortCallers}}" class="clickable" title="Method">{{ profileCallersTable.getColumnLabel(1) }}</th>
              </tr>
              </thead>
              <tbody id="callers-table">
              </tbody>
            </table>
          </div>
          <hr>
          <div class="call-table scroll">
            <table class="full-width table">
              <thead>
              <tr>
                <th on-click="{{changeSortCallees}}" class="clickable" title="Callees (%)">{{ profileCalleesTable.getColumnLabel(0) }}</th>
                <th on-click="{{changeSortCallees}}" class="clickable" title="Method">{{ profileCalleesTable.getColumnLabel(1) }}</th>
              </tr>
              </thead>
              <tbody id="callees-table">
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
    <br>
    <br>
    <div class="focused-function-label">
      <template if="{{ focusedFunction != null }}">
        <span>Filtered tree: </span>
        <function-ref ref="{{ focusedFunction }}"></function-ref>
      </template>
      <template if="{{ focusedFunction == null }}">
        <span>No focused function</span>
      </template>
    </div>
    <div class="flex-row centered">
      <div class="flex-item-90-percent outlined" style="margin: 16px; margin-left: 8px; margin-right: 8px">
        <table class="full-width tree">
          <thead id="treeHeader">
          <tr>
            <th>Method</th>
            <th>Executing</th>
          </tr>
          </thead>
          <tbody id="treeBody">
          </tbody>
        </table>
      </div>
    </div>
  </template>
</polymer-element>

<polymer-element name="cpu-profile" extends="observatory-element">
  <template>
    <link rel="stylesheet" href="css/shared.css">
    <nav-bar>
      <top-nav-menu></top-nav-menu>
      <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
      <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
      <nav-menu link="{{ makeLink('/profiler', isolate) }}" anchor="cpu profile" last="{{ true }}"></nav-menu>
      <nav-refresh callback="{{ refresh }}"></nav-refresh>
      <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
    </nav-bar>
    <style>
      .tableWell {
        background-color: #ECECEC;
        padding: 0.2em;
      }

      .table {
        border-spacing: 0px;
        width: 100%;
        margin-bottom: 20px
        vertical-align: middle;
      }

      tr {
        background-color: #FFFFFF;
      }

      tbody tr {
        animation: fadeIn 0.5s;
        -moz-animation: fadeIn 0.5s;
        -webkit-animation: fadeIn 0.5s;
      }

      tbody tr:hover {
        background-color: #FAFAFA;
      }

      tr td:first-child,
      tr th:first-child {
        width: 100%;
      }

      .table thead > tr > th {
        padding: 8px;
        vertical-align: bottom;
        text-align: left;
        border-bottom: 1px solid #ddd;
      }

      .infoBox {
        position: absolute;
        top: 100%;
        left: 0%;
        z-index: 999;
        opacity: 1;
        padding: 1em;
        background-color: #ffffff;
        border-left: solid 2px #ECECEC;
        border-bottom: solid 2px #ECECEC;
        border-right: solid 2px #ECECEC;
      }

      .statusMessage {
        font-size: 150%;
        font-weight: bold;
      }

      .statusBox {
        height: 100%;
        padding: 1em;
      }

      .center {
        align-items: center;
        justify-content: center;
      }

      .notice {
        background-color: #fcf8e3;
      }

      .red {
        background-color: #f2dede;
      }

    </style>
    <div class="content-centered-big">
      <h1>Sampled CPU profile</h1>
      <hr>
      <template if="{{ state == 'Requested' }}">
        <div class="statusBox shadow center">
          <div class="statusMessage">Fetching profile from VM...</div>
        </div>
      </template>
      <template if="{{ state == 'Loading' }}">
        <div class="statusBox shadow center">
          <div class="statusMessage">Loading profile...</div>
        </div>
      </template>
      <template if="{{ state == 'Disabled' }}">
        <div class="statusBox shadow center">
          <div>
            <h1>Profiling is disabled</h1>
            <br>
            Perhaps the <b>profile</b> flag has been disabled for this VM.
            <br><br>
            See all
            <a on-click="{{ goto }}" _href="{{ gotoLink('/flags') }}">vm flags</a>
          </div>
        </div>
      </template>
      <template if="{{ state == 'Exception' }}">
        <div class="statusBox shadow center">
          <div class="statusMessage">
            <h1>Profiling is disabled due to unexpected exception:</h1>
            <br>
            <pre>{{ exception.toString() }}</pre>
            <br>
            <h1>Stack trace:</h1>
            <br>
            <pre>{{ stackTrace.toString() }}</pre>
          </div>
        </div>
      </template>
      <template if="{{ state == 'Loaded' }}">
        <div class="memberList">
          <div class="memberItem">
            <div class="memberName">Refreshed at </div>
            <div class="memberValue">{{ refreshTime }} (fetched in {{ fetchTime  }}) (loaded in {{ loadTime }})</div>
          </div>
          <div class="memberItem">
            <div class="memberName">Profile contains</div>
            <div class="memberValue">{{ sampleCount }} samples (spanning {{ timeSpan }})</div>
          </div>
          <div class="memberItem">
            <div class="memberName">Sampling</div>
            <div class="memberValue">{{ stackDepth }} stack frames @ {{ sampleRate }} Hz</div>
          </div>
          <div class="memberItem">
            <div class="memberName">Mode</div>
            <div class="memberValue">
              <select value="{{modeSelector}}">
                <option value="Code">Code</option>
                <option value="Function">Function</option>
              </select>
            </div>
          </div>
          <div class="memberItem">
            <div class="memberName">Tag Order</div>
            <div class="memberValue">
              <select value="{{tagSelector}}">
                <option value="UserVM">User &gt; VM</option>
                <option value="UserOnly">User</option>
                <option value="VMUser">VM &gt; User</option>
                <option value="VMOnly">VM</option>
                <option value="None">None</option>
              </select>
            </div>
          </div>
          <!--- Experimental
          <div class="memberItem">
            <div class="memberName">Call Tree Direction</div>
            <div class="memberValue">
              <select value="{{directionSelector}}">
                <option value="Down">Top down</option>
                <option value="Up">Bottom up</option>
              </select>
            </div>
          </div>
           --->
        </div>
      </template>
      <template if="{{ state == 'Loaded' && directionSelector == 'Down' }}">
        <br>
        <div class="statusBox shadow">
          <div>Tree is rooted at main.</div>
          <br>
          <div>Child nodes are callees.</div>
          <br>
          <div class="notice">To get the most out of this mode you may need to launch Dart with a higher --profile-depth flag value.</div>
          <div class="notice">Try 16, 32, ... up to 256 until [Truncated] approaches zero.</div>
          <div class="red">NOTE: Higher values will impact performance</div>
        </div>
      </template>
      <template if="{{ state == 'Loaded' && directionSelector == 'Up' }}">
        <br>
        <div class="statusBox shadow">
          <div>Tree is rooted at executing function / code.</div>
          <br>
          <div>Child nodes are callers.</div>
        </div>
      </template>
      <br><br>
      <div class="tableWell shadow">
        <table class="table">
          <thead id="treeHeader">
          <tr>
            <th>Method</th>
            <th>Executing</th>
          </tr>
          </thead>
          <tbody id="treeBody">
          </tbody>
        </table>
      </div>
    </div>
    <view-footer></view-footer>
  </template>
</polymer-element>

<script type="application/dart" src="cpu_profile.dart"></script>
